package com.jt.www.biz.user_wxb.service.impl;

import com.jt.www.biz.user_wxb.service.WeChatAppLoginService;
import com.jt.www.dao.mapper.wx.WechatUserMapper;
import com.jt.www.model.remote.user.LoginResultVO;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.wx.*;
import com.jt.www.remote.UserClient;
import com.jt.www.remote.wx.WeChatApi;
import com.jt.www.util.JsonUtil;
import com.jt.www.util.wx.WxUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class WeChatAppLoginServiceImpl implements WeChatAppLoginService {

    public static final Logger log = LoggerFactory.getLogger(WeChatAppLoginServiceImpl.class);

    private static final String GRANT_TYPE = "authorization_code";
    //private static final String     APP_ID = "wx29fc58b2cd2cff1b";
    //private static final String     APP_SECRET = "5d736a2f582ef6401f8575ca7c7bf760";
    private static final String CHANNEL_NO = "edu";
    //用户注册时密码使用md5加密后的字符  该密码为edu
    private static final String PASSWORD = "379ef4bd50c30e261ccfb18dfc626d9f";
    private static final String CLIENT_WXB = "wxb";
    private static final String CLIENT_YH = "yh";
    private static final String CLIENT_ZYD = "zyd";
    //我学保小程序
    private static final String WXB_APP_ID = "wxa528fce63ba69155";
    private static final String WXB_APP_SECRET = "c33699d5bc8d4b4cf2551f17ca3b91ee";
    //隐患排查小程序
    private static final String YH_APP_ID = "wxc8778cf3bae16981";
    private static final String YH_APP_SECRET = "fddced563f3fc4b801f2f7e0d788c424";
    //展业端
    private static final String ZYD_APP_ID = "wxf8879c6933ed31f9";
    private static final String ZYD_APP_SECRET = "66716c532c7c8590868f6d762fd3ee31";

    @Autowired
    private WeChatApi weChatApi;
    @Autowired
    private UserClient userClient;
    @Autowired
    private WechatUserMapper wechatUserMapper;

    @Override
    public UserInfoVO getUserInfo(WxParamBean wxParamBean) throws Exception {
        if (StringUtils.isEmpty(wxParamBean.getClientType())) {
            log.error("clientType不能未空 wxb-我学保，yh-隐患排查，zyd-展业端");
            throw new Exception("客户端类型无法确认");
        }
        String jsonStr;
        String sysCode = "sys_edu_wxb_pc";
        switch (wxParamBean.getClientType()) {
            case CLIENT_WXB:
                jsonStr = weChatApi.code2session(WXB_APP_ID, WXB_APP_SECRET, wxParamBean.getCode(), GRANT_TYPE);
                break;
            case CLIENT_YH:
                jsonStr = weChatApi.code2session(YH_APP_ID, YH_APP_SECRET, wxParamBean.getCode(), GRANT_TYPE);
                break;
            case CLIENT_ZYD:
                jsonStr = weChatApi.code2session(ZYD_APP_ID, ZYD_APP_SECRET, wxParamBean.getCode(), GRANT_TYPE);
                sysCode = "sys_edu_man";
                break;
            default:
                log.error("clientType：{}， wxb-我学保，yh-隐患排查，zyd-展业端", wxParamBean.getClientType());
                throw new Exception("未知的客户端类型");
        }
        if (StringUtils.isEmpty(jsonStr)) {
            throw new Exception("系统繁忙，请重试");
        }
        WeChatAuthBean weChatAuthBean = JsonUtil.json2Object(jsonStr, WeChatAuthBean.class);
        if (weChatAuthBean == null) {
            throw new Exception("系统繁忙，请重试");
        }
        if (weChatAuthBean.getErrCode() != 0) {
            throw new Exception(weChatAuthBean.getErrMsg());
        }
        String phoneNum = this.getPhoneNum(wxParamBean.getEncryptedData(), weChatAuthBean.getSessionKey(), wxParamBean.getIv(), wxParamBean.getClientType());
        LoginResultVO userInfo = getUserInfo(weChatAuthBean.getOpenId(), phoneNum, weChatAuthBean.getUnionId(), sysCode);

        // 展业端 level = 03、05才允许登录
        if (CLIENT_ZYD.equals(wxParamBean.getClientType())) {
            if (!"03".equals(userInfo.getLevel()) && !"05".equals(userInfo.getLevel())) {
                return null;
            }
        } else if (CLIENT_YH.equals(wxParamBean.getClientType())) {//隐患排查只允许风管所工程师和隐患排查业务员登录
            if (!eduQueryUserRole(userInfo.getLoginAccount())) {
                return null;
            }
        }
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setToken(userInfo.getToken());
        userInfoVO.setRefreshToken(userInfo.getRefreshToken());
        userInfoVO.setPhoneNum(phoneNum);
        userInfoVO.setUserCode(userInfo.getUserCode());
        userInfoVO.setUserName(userInfo.getUserName());
        userInfoVO.setBranchName(userInfo.getBranchName());
        userInfoVO.setTokenExpireTime(userInfo.getTokenExpireTime());
        Date date = new Date();
        WechatUser wechatUser = new WechatUser();
        wechatUser.setOpenId(weChatAuthBean.getOpenId());
        wechatUser.setPhoneNum(phoneNum);
        wechatUser.setClientType(wxParamBean.getClientType());
        wechatUser.setCreateTime(date);
        wechatUser.setUserCode(userInfo.getUserCode());
        wechatUser.setUserName(userInfo.getUserName());
        wechatUser.setBranchName(userInfo.getBranchName());
        try {
            wechatUserMapper.insert(wechatUser);
        } catch (Exception e) {
            e.printStackTrace();
            return userInfoVO;
        }
        return userInfoVO;
    }

    @Override
    public JudgeUserVO judgeUserExists(String code, String clientType) throws Exception {
        String jsonStr;
        String sysCode = "sys_edu_wxb_pc";
        switch (clientType) {
            case CLIENT_WXB:
                jsonStr = weChatApi.code2session(WXB_APP_ID, WXB_APP_SECRET, code, GRANT_TYPE);
                break;
            case CLIENT_YH:
                jsonStr = weChatApi.code2session(YH_APP_ID, YH_APP_SECRET, code, GRANT_TYPE);
                break;
            case CLIENT_ZYD:
                jsonStr = weChatApi.code2session(ZYD_APP_ID, ZYD_APP_SECRET, code, GRANT_TYPE);
                sysCode = "sys_edu_man";
                break;
            default:
                log.error("clientType：{}， wxb-我学保，yh-隐患排查，zyd-展业端", clientType);
                throw new Exception("未知的客户端类型");
        }
        if (StringUtils.isEmpty(jsonStr)) {
            log.error("errormsg:{}", jsonStr);
            throw new Exception("系统繁忙，请重试");
        }
        WeChatAuthBean weChatAuthBean = JsonUtil.json2Object(jsonStr, WeChatAuthBean.class);
        if (weChatAuthBean == null) {
            throw new Exception("系统繁忙，请重试");
        }
        if (weChatAuthBean.getErrCode() != 0) {
            throw new Exception(weChatAuthBean.getErrMsg());
        }
        String openId = weChatAuthBean.getOpenId();
        String unionId = weChatAuthBean.getUnionId();
        String sessionKey = weChatAuthBean.getSessionKey();
        WechatUser wechatUser = wechatUserMapper.findByOpenId(openId);
        JudgeUserVO judgeUserVO = new JudgeUserVO();
        if (wechatUser == null) {
            judgeUserVO.setIsExist("0");
            return judgeUserVO;
        } else {
            LoginResultVO userInfo = getUserInfo(openId, wechatUser.getPhoneNum(), unionId, sysCode);
            judgeUserVO.setIsExist("1");
            judgeUserVO.setPhoneNum(userInfo.getPhone());
            judgeUserVO.setToken(userInfo.getToken());
            judgeUserVO.setRefreshToken(userInfo.getRefreshToken());
            judgeUserVO.setTokenExpireTime(userInfo.getTokenExpireTime());
            judgeUserVO.setUserCode(userInfo.getUserCode());
            judgeUserVO.setUserName(userInfo.getUserName());
            judgeUserVO.setBranchName(userInfo.getBranchName());
            return judgeUserVO;
        }
    }

    private String getPhoneNum(String encryptedData, String sessionKey, String iv, String clientType) throws Exception {
        String s = WxUtils.wxDecrypt(encryptedData, sessionKey, iv);
        WxPhoneBean wxPhoneBean = JsonUtil.json2Object(s, WxPhoneBean.class);
        if (wxPhoneBean == null) {
            throw new Exception("系统繁忙，请重试");
        }
        WaterMark watermark = wxPhoneBean.getWatermark();
        if (watermark == null) {
            throw new Exception("系统繁忙，请重试");
        }
        switch (clientType) {
            case CLIENT_WXB:
                if (!StringUtils.equals(watermark.getAppid(), WXB_APP_ID)) {
                    throw new Exception("非法登陆");
                }
                break;
            case CLIENT_YH:
                if (!StringUtils.equals(watermark.getAppid(), YH_APP_ID)) {
                    throw new Exception("非法登陆");
                }
                break;
            case CLIENT_ZYD:
                if (!StringUtils.equals(watermark.getAppid(), ZYD_APP_ID)) {
                    throw new Exception("非法登陆");
                }
                break;
            default:
                log.error("clientType：{}， wxb-我学保，yh-隐患排查，zyd-展业端", clientType);
                throw new Exception("未知的客户端类型");
        }

        return wxPhoneBean.getPhoneNumber();
    }


    @Override
    public String getUserCode(String phoneNum) throws Exception {
        String userCode;
        GenericDataResponse<Map<String, String>> result = userClient.queryUserIsExist(phoneNum);
        verifyResult(result);
        //手机号未注册
        if (StringUtils.equals(result.getData().get("isExist"), "0")) {
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("channelCode", CHANNEL_NO);
            //小程序没有密码，所以入参默认一个密码
            paramMap.put("password", PASSWORD);
            paramMap.put("userLoginId", phoneNum);
            //注册
            GenericDataResponse<String> register = userClient.register(paramMap);
            verifyResult(register);
            userCode = register.getData();
        } else {
            userCode = result.getData().get("userCode");
        }
        return userCode;
    }

    private LoginResultVO getUserInfo(String openId, String phoneNum, String unionId, String sysCode) throws Exception {
        String userCode = getUserCode(phoneNum);
        ResponseEntity<GenericDataResponse<LoginResultVO>> userResult = userClient.queryInfoByUserCode(userCode, sysCode);
        GenericDataResponse<LoginResultVO> userInfo = userResult.getBody();
        verifyResult(userInfo);
        return userInfo.getData();
    }

    private void verifyResult(GenericDataResponse<?> result) throws Exception {
        if (result == null) {
            throw new Exception("系统繁忙，请重试");
        }
        if (StringUtils.equals(result.getCode(), "9999")) {
            throw new Exception(result.getMsg());
        }
    }

    /**
     * 根据登陆账号查询用户角色信息（隐患排查业务员、风管所工程师）
     *
     * @param userLoginId
     * @return
     */
    private Boolean eduQueryUserRole(String userLoginId) {
        try {
            GenericDataResponse<Map<String, Object>> result = userClient.eduQueryUserRole(userLoginId);
            if ("0000".equals(result.getCode())) {
                ArrayList<Map<String, Object>> list = (ArrayList<Map<String, Object>>) result.getData().get("roleList");
                return list != null && list.size() > 0;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
